package com.lingjtx.common.thread.api;

import com.lingjtx.common.core.model.api.OssUploadResponseItem;
import com.lingjtx.common.core.model.api.OssUploadStream;
import com.lingjtx.common.core.model.iot.MqttRequest;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * 此类功能跟 client-api 模块功能一致。但灵活性和高性能比 Feign 更加好
 * 如果是响应式编程推荐使用此类来进行微服务之间调用，异步调用推荐使用 MQ 进行，WebClientApi 也能进行同步异步调用
 */
public class WebClientApi {

    private WebClientExecutor webClientExecutor;

    public WebClientApi webClientExecutor(WebClientExecutor executor) {
        this.webClientExecutor = executor;
        return this;
    }

    /**
     * 上传文件流到私有 oss
     */
    public Mono<OssUploadResponseItem> singleUpload(OssUploadStream model) {
        return webClientExecutor.execute(webClient -> webClient.post()
                .uri("/oss/pri/upload/single/stream")
                .bodyValue(model)
                .retrieve()
                .onStatus(HttpStatusCode::isError, response -> response.bodyToMono(String.class)
                        .map(body -> new RuntimeException("Request failed: " + body))
                )
                .bodyToMono(OssUploadResponseItem.class));
    }

    public Mono<String> sendIotCmd(MqttRequest model) {
        return webClientExecutor.execute(webClient -> webClient.post()
                .uri("/iot-network/cmd/send")
                .bodyValue(model)
                .retrieve()
                .onStatus(HttpStatusCode::isError, response -> response.bodyToMono(String.class)
                        .map(body -> new RuntimeException("Request failed: " + body))
                )
                .bodyToMono(String.class));
    }

    /**
     * 获取群聊的成员列表
     */
    public Mono<List<Long>> getGroupMemberIds(Long groupId) {
        return webClientExecutor.execute(webClient -> webClient.post()
                .uri(uriBuilder -> uriBuilder
                        .path("/chat_messages/group/{groupId}")
                        .build(groupId))
                .contentType(MediaType.APPLICATION_JSON)
                .retrieve()
                .onStatus(HttpStatusCode::isError, response -> response.bodyToMono(String.class)
                        .map(body -> new RuntimeException("Request failed: " + body))
                )
                .bodyToMono(new ParameterizedTypeReference<>() {
                }));
    }

    /**
     * 获取客服坐席人员列表
     */
    public Mono<List<Long>> getKefuSeatIds(Long groupId) {
        return webClientExecutor.execute(webClient -> webClient.post()
                .uri(uriBuilder -> uriBuilder
                        .path("/kefu/group/{groupId}")
                        .build(groupId))
                .contentType(MediaType.APPLICATION_JSON)
                .retrieve()
                .onStatus(HttpStatusCode::isError, response -> response.bodyToMono(String.class)
                        .map(body -> new RuntimeException("Request failed: " + body))
                )
                .bodyToMono(new ParameterizedTypeReference<>() {
                }));
    }
}
